import 'dart:async';
import 'dart:collection';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flame/events.dart';
import 'package:flame/flame.dart';
import 'package:flame/palette.dart';
import 'package:flutter/material.dart';
import 'package:flame/components.dart';
import 'package:freedom/page/mahjong/bloc/user_state.dart';
import 'package:freedom/page/mahjong/event/user_cell_event.dart';
import 'package:freedom/page/mahjong/event/user_prepare_event.dart';
import 'package:freedom/page/mahjong/event/user_state_event.dart';
import 'package:freedom/page/mahjong/mahjong_game.dart';
import 'package:freedom/page/mahjong/message/action_message.dart';
import '../common/mahjong_context.dart';
import '../util/user_location.dart';
import 'message_util.dart';

class MessageInfo {
  String id;
  String message;
  int sleep;
  MessageInfo(this.id, this.message, {this.sleep = 2});
}

class HeadImageComponent extends PositionComponent
    with TapCallbacks, HasGameRef<MahjongIndexGame> {
  String backGrd = 'mahjong/user/header/header_border.png';
  Sprite? sprite;
  Sprite? _readingSprite;
  String? message;
  Direction direction;
  late UserState userState;

  final Queue<MessageInfo> messageQueue = Queue();

  MessageInfo? currentMessage;

  final double _headImageHeight = MahjongContext().headImageHeight;
  // 文字   图片  大小
  final double _ifHeight = MahjongContext().headImageHeight / 3;
  late Vector2 _userNamePosition;

  HeadImageComponent({Vector2? size, this.message, required this.direction})
      : super(size: size ?? Vector2.all(MahjongContext().headImageHeight));
  @override
  void onTapDown(TapDownEvent event) {
    game.setSelectUser(userState);
    MahjongContext().showOverlay(MahjongOverlay.userInfoDialog);
    super.onTapDown(event);
  }

  //添加消息
  void pushMessage(MessageInfo? message) {
    if (message == null) {
      return;
    }
    messageQueue.add(message);
  }

  // 主动退出消息
  void exitMessage(String messageId) {
    // 判断当前消息是否为退出消息
    if (currentMessage != null && currentMessage!.id == messageId) {
      currentMessage = null;
      message = null;
      realTime = 0;
    } else {
      messageQueue.removeWhere((element) => element.id == messageId);
    }
  }

  @override
  bool containsLocalPoint(Vector2 point) {
    return Rect.fromLTWH(0, 0, size.x, size.y)
        .contains(Offset(point.x, point.y));
  }

  double realTime = 0;

  @override
  void update(double dt) {
    realTime += dt;
    // 如果当前没有显示得消息  然后队列里面又有消息
    if (currentMessage == null && messageQueue.isNotEmpty) {
      // 取出消息,重置计时器
      currentMessage = messageQueue.removeFirst();
      message = currentMessage!.message;
      realTime = 0;
    }
    // 如果显示得消息不为空  然后计时器得时间达到了  清空消息
    if (currentMessage != null && realTime > currentMessage!.sleep) {
      message = null;
      currentMessage = null;
      realTime = 0;
    }

    super.update(dt);
  }

  void updateOnline(bool online) {
    userState.online = online;
  }

  @override
  Future<void> onLoad() async {
    userState = MahjongContext.getUserState(direction)!;
    MahjongContext.registerUserFunc<UserCellEvent>(userState.userId, (event) {
      userState.listen = true;
    });

    MahjongContext.registerUserFunc<UserPrepareEvent>(userState.userId,
        (event) {
      if (event.reading) {
        userState.beforeCompleted = ActionMessageHandler.PREPARE;
      } else {
        userState.beforeCompleted = "";
      }
      userState.listen = false;
    });

    // 用户状态变更
    MahjongContext.registerUserFunc<UserStateUpdateEvent>(userState.userId,
        (event) {
      userState = event.userState;
    });
    _readingSprite =
        Sprite(Flame.images.fromCache('mahjong/commons/reading.png'));
/*    final byteData = await NetworkAssetBundle(Uri.parse(imageUrl)).load('');
    final bytes = byteData.buffer.asUint8List();
    final image = await decodeImageFromList(bytes);*/
    var textStyle = TextStyle(
        color: Colors.white,
        fontSize: _ifHeight,
        height: 1.0,
        overflow: TextOverflow.ellipsis);
    var userNameText =
        TextSpan(text: '${userState.username}', style: textStyle);
    var userNamePainter = TextPainter(
      text: userNameText,
      textDirection: TextDirection.ltr,
      ellipsis: ".",
      maxLines: 1,
    );
    userNamePainter.layout(maxWidth: _headImageHeight);

    switch (direction) {
      case Direction.BOTTOM:
        position = MahjongContext().bImagePoint;
        size.setValues(size.x * 2, size.y);
        _userNamePosition = Vector2(
            size.x * 3 / 4 - userNamePainter.width / 2, userNamePainter.height);
        break;
      case Direction.TOP:
        position = MahjongContext().tImagePoint;
        size.setValues(size.x * 2, size.y);
        _userNamePosition = Vector2(
            size.x * 3 / 4 - userNamePainter.width / 2, userNamePainter.height);
        break;
      case Direction.LEFT:
        position = MahjongContext().lImagePoint;
        size.setValues(size.x, size.y + _ifHeight * 2);
        _userNamePosition = Vector2(0, _headImageHeight);
        break;
      case Direction.RIGHT:
        position = MahjongContext().rImagePoint;
        size.setValues(size.x, size.y + _ifHeight * 2);
        _userNamePosition = Vector2(0, _headImageHeight);
        break;
      default:
        size.setValues(size.x * 2, size.y);
    }
    add(TextBoxComponent(
        text: "${userState.username}",
        position: _userNamePosition,
        boxConfig: TextBoxConfig(
          maxWidth: _headImageHeight,
          growingBox: true,
          margins: const EdgeInsets.all(0),
        ),
        align: Anchor.centerLeft,
        size: Vector2(_headImageHeight, _ifHeight),
        textRenderer: TextPaint(style: textStyle)));

    /*  CachedNetworkImage(
      imageUrl: 'https://example.com/image.jpg', // 图片URL
      placeholder: (context, url) => CircularProgressIndicator(), // 占位符
      errorWidget: (context, url, error) => Icon(Icons.error), // 错误显示
      fit: BoxFit.cover, // 图片适应方式
      width: 200, // 图片宽度
      height: 200, // 图片高度
    );*/
    // 这里会发生网络请求
    final imageStream = CachedNetworkImageProvider(userState.portraitUrl!)
        .resolve(ImageConfiguration.empty);
    imageStream.addListener(ImageStreamListener((info, _) {
      final image = info.image;
      sprite = Sprite(image);
    }, onError: (Object exception, StackTrace? stackTrace) {
      sprite = Sprite(
          Flame.images.fromCache('mahjong/user/header/common_header.png'));
    }));
    //加载默认图片1
    /*sprite =
        Sprite(Flame.images.fromCache('mahjong/user/header/common_header.png'));*/
  }

  @override
  void render(Canvas canvas) {
    var fontSize = size.y > size.x ? size.x / 3 : size.y / 3;
    var itemWidth = size.y > size.x ? size.x : size.y;
    var scoreStyle = TextStyle(
        color: Colors.yellow,
        fontSize: _ifHeight,
        height: 1.0,
        fontWeight: FontWeight.bold);
    /**====== 分数信息开始 ======*/
    String scoreStr = userState.score >= 0
        ? userState.score.toString()
        : ("${userState.score.abs()}-");
    var scoreText = TextSpan(text: scoreStr, style: scoreStyle);
    var scorePainter = TextPainter(
      text: scoreText,
      textDirection: TextDirection.rtl,
    );
    scorePainter.layout();

    /**====== 背景信息开始 ======*/
    Paint backgroundPaint = Paint();
    backgroundPaint
      ..color = const Color(0x818181BD)
      ..style = PaintingStyle.fill;
    RRect clipRect =
        RRect.fromLTRBR(0, 0, size.x, size.y, const Radius.circular(3.0));
    canvas.drawRRect(clipRect, backgroundPaint);
    Vector2 messagePosition = Vector2(MahjongContext().headImageHeight, 0);
    if (message != null) {
      MessageUtil.drawMessage(canvas, message!,
          start: messagePosition, direction: direction);
    }
    Rect headImageRect;
    Vector2 readingSize = Vector2.all(MahjongContext().headImageHeight);
    var borderWidth = 0.0;
    late Offset scoreOffset;
    late Vector2 readingPosition;
    Offset listenPosition = const Offset(0, 0);
    switch (direction) {
      case Direction.BOTTOM:
      case Direction.TOP:
        readingPosition = Vector2(size.x, 0);
        headImageRect = Rect.fromLTWH(borderWidth, borderWidth,
            size.x / 2 - borderWidth * 2, size.y - borderWidth * 2);
        scoreOffset =
            Offset(size.x * 3 / 4 - scorePainter.width / 2, size.y - _ifHeight);
        listenPosition = Offset(size.x * 3 / 4 - _ifHeight / 2, 0);
        break;
      case Direction.LEFT:
      case Direction.RIGHT:
        readingPosition =
            Vector2(direction == Direction.LEFT ? size.x : -size.x, 0);
        headImageRect = Rect.fromLTWH(borderWidth, borderWidth,
            size.x - borderWidth * 2, _headImageHeight);
        scoreOffset = Offset(
            (size.x - scorePainter.width) / 2, _headImageHeight + _ifHeight);
        listenPosition = Offset(
            direction == Direction.LEFT
                ? size.x + _ifHeight / 2
                : -_ifHeight * 1.5,
            0);
        break;
    }
    if (sprite != null) {
      sprite!.renderRect(canvas, headImageRect);
    }
    scorePainter.paint(canvas, scoreOffset);
    /**====== 用户准备开始 ======*/
    if (userState.getBeforeActions().contains(ActionMessageHandler.PREPARE)) {
      _readingSprite?.render(canvas,
          position: readingPosition, size: readingSize);
    }
    /**====== 用户听牌开始 ======*/
    if (userState.listen) {
      /**====== 听牌背景色 ======*/
      final rect = Rect.fromLTWH(
          listenPosition.dx, listenPosition.dy, _ifHeight, _ifHeight);
      final paint = Paint()..color = const Color.fromARGB(255, 1, 130, 210);
      canvas.drawRect(rect, paint);
      var listenPainter = TextPainter(
        text: TextSpan(
            text: '听',
            style: TextStyle(
                color: Colors.white,
                fontSize: _ifHeight,
                height: 1.0,
                fontWeight: FontWeight.bold,
                overflow: TextOverflow.ellipsis)),
        textDirection: TextDirection.ltr,
        ellipsis: ".",
        maxLines: 1,
      );
      listenPainter.layout(maxWidth: itemWidth);
      listenPainter.paint(canvas, listenPosition);
    }
    /**====== 用户离线开始 ======*/
    if (!userState.online) {
      Rect coverRect = Rect.fromLTWH(
          borderWidth, borderWidth, headImageRect.width, headImageRect.height);
      Paint coverPaint = Paint()
        ..color = const Color.fromARGB(220, 146, 146, 146)
        ..style = PaintingStyle.fill;
      canvas.drawRect(coverRect, coverPaint);

      var offLinePainter = TextPainter(
        text: TextSpan(
            text: '离线',
            style: TextStyle(
                color: const Color.fromARGB(255, 255, 255, 255),
                fontSize: fontSize,
                overflow: TextOverflow.ellipsis)),
        textDirection: TextDirection.ltr,
        ellipsis: ".",
        maxLines: 1,
      );
      offLinePainter.layout(maxWidth: itemWidth);
      offLinePainter.paint(
          canvas,
          Offset((headImageRect.width - offLinePainter.width) / 2,
              (headImageRect.height - offLinePainter.height) / 2));
    }

    super.render(canvas);
  }
}

final _regularTextStyle = TextStyle(
  fontSize: 18,
  color: BasicPalette.white.color,
);
final _regular = TextPaint(
  style: _regularTextStyle,
);
final _tiny = TextPaint(style: _regularTextStyle.copyWith(fontSize: 14.0));
final _box = _regular.copyWith(
  (style) => style.copyWith(
    color: Colors.lightGreenAccent,
    fontFamily: 'monospace',
    letterSpacing: 2.0,
  ),
);
final _shaded = TextPaint(
  style: TextStyle(
    color: BasicPalette.white.color,
    fontSize: 40.0,
    shadows: const [
      Shadow(color: Colors.red, offset: Offset(2, 2), blurRadius: 2),
      Shadow(color: Colors.yellow, offset: Offset(4, 4), blurRadius: 4),
    ],
  ),
);

class MyTextBox extends TextBoxComponent {
  late Paint paint;
  late Rect bgRect;

  MyTextBox(
    String text, {
    super.align,
    super.size,
    double? timePerChar,
    double? margins,
  }) : super(
          text: text,
          textRenderer: _box,
          boxConfig: TextBoxConfig(
            maxWidth: 400,
            timePerChar: timePerChar ?? 0.05,
            growingBox: true,
            margins: EdgeInsets.all(margins ?? 25),
          ),
        );

  @override
  Future<void> onLoad() {
    paint = Paint();
    bgRect = Rect.fromLTWH(0, 0, width, height);
    size.addListener(() {
      bgRect = Rect.fromLTWH(0, 0, width, height);
    });

    paint.color = Colors.white10;
    return super.onLoad();
  }

  @override
  void render(Canvas canvas) {
    canvas.drawRect(bgRect, paint);
    super.render(canvas);
  }
}
